package android_serialport_api;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class ZigbeeAdapter extends SerialPortActivity {

	// zigbee数据命令字
	final static int FRAME_START_UP = 0xA5;
	final static int FRAME_START_DOWN = 0xAC;
	final static int COMMAND_HANDSHAKE = 0xAA;
	final static int COMMAND_DATABRIDGE = 0xDA;
	final static int COMMAND_DEVICE_REPORT = 0xFD;
	final static int COMMAND_RESET = 0xFE;
	final static int COMMAND_SUBDEVICE_INFO = 0xF4; 
	final static int COMMAND_HANDSHAKE_ANSWER = 0xAD; 
		
	final static int ZD_READ = 0x01;
	final static int ZD_ACT = 0x03;
	
	private static int loc = 0;	  //标志位，表示在缓冲区中的位置
	private static byte[] RcvBuf; //大的缓冲区，用于保存串口数据，从中分析数据
	
	private static int actNum = 0; //继电器模块执行次数
	byte[] actsAddr;	//继电器类模块地址
	byte[] sensorAddr;  //传感器类模块地址

	// 消息编号
	final static int SENSORDEVMSG = 1;	// 传感器消息
	final static int ACTDEVMSG = 2;     // 继电器类设备消息
	
	public static Handler myhandler = null;
		
	public ZigbeeAdapter(Handler handler){
		//初始化全局变量
		myhandler = handler;
		RcvBuf = new byte[2048];
		actsAddr = new byte[2];
		sensorAddr = new byte[2];
	}

	public void initSerial(String dev,int baudrates){
		//打开串口
		openSerial(new File(dev), baudrates);
	}
	
	public void closeSerial(){
		try {
			closeSerialPort();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void devHands(){
		byte[] cmdBuf;
		cmdBuf = new byte[2];
		cmdBuf[0] = (byte) FRAME_START_DOWN;
		cmdBuf[1] = (byte) COMMAND_HANDSHAKE;
		try {
			mOutputStream.write(cmdBuf);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected void onDataReceived(final byte[] buffer, final int size) {
		// TODO Auto-generated method stub
			// 收到数据后，利用串口状态机，读取串口数据
			if (size > 0) {
			    //Log.v("hwp_debug onDataReceived", new String(buffer, 0, size));
                //Log.v("size长度", size+"");
				System.arraycopy(buffer, 0, RcvBuf, loc, size);
				loc += size;
				controllerRecieveData(RcvBuf, loc);
				if (loc > 1024) {
					loc = 0;
				}
			}
		}
	
	//从大buffer中，循环处理接收到的数据
	private void controllerRecieveData(byte[] buffer, int size) {
		int len = 1024;
		if(len < buffer.length+1) len = buffer.length+1;
		byte[] Buf = new byte[len];
		System.arraycopy(buffer, 0, Buf, 0, size);
		int machineState = 0; // 状态机标示位
		int cmdBegin = 0;
		int datalen = size;

		for (int i = 0; i < datalen;) {
			if (machineState == 0) {
				if ((Buf[i] & 0xFF) != FRAME_START_UP) { // 无效数据,忽略
					i++;
					continue;
				}
				cmdBegin = i; // 找到命令开头，解析命令
				machineState = 1;
				i++;
				continue;
			} else if (machineState == 1) {
				if ((Buf[i] & 0xFF) == COMMAND_HANDSHAKE_ANSWER) { //握手答复指令
					// 协调器在工作
					machineState = 0;
					i++;
				} else if ((Buf[i] & 0xFF) == COMMAND_HANDSHAKE) { //握手指令
					devHands();
					// 握手成功
					machineState = 0;
					i++;
				} else if ((Buf[i] & 0xFF) == COMMAND_DATABRIDGE) { //数据指令
					i++;
					int dataleft = datalen - i;
					int cmdLen;
					if (dataleft < 3) {
						break;
					}
					cmdLen = 3 + (Buf[i + 2] & 0xFF);
			
					if ((dataleft < cmdLen)) {
						break; // 数据不完整，退出
					}
					// 查看数据是否完整 2byte addr + 1byte len +data
					// 数据完整，取指令数据
					byte[] tempBuf = new byte[cmdLen + 1];
					System.arraycopy(Buf, cmdBegin, tempBuf, 0, cmdLen + 1);
					
					//处理具体的数据
					if (DeviceDataReceived(tempBuf) == 0)
							break;
						i += cmdLen;
						machineState = 0;
					} else {
						i++;
					}
				} else {
					i++;
				}
			}

			if (machineState == 1) {
				System.arraycopy(RcvBuf, cmdBegin, RcvBuf, 0, datalen - cmdBegin);
				loc = datalen - cmdBegin;
			} else {
				loc = 0;
			}
		}
	
	private int DeviceDataReceived(byte[] data) {

		byte[] sAddr = new byte[2];	//模块自身短地址
		byte[] pAddr = new byte[2];	//模块父地址
		byte[] lAddr = new byte[8]; //模块自身长地址
		//byte[] nSub = new byte[2];	//子设备号
		
		int i = 5;
		if (data.length <= 5)
			return 0;
		if ((data[i] & 0xFF) == COMMAND_DEVICE_REPORT) {	//模块信息上报指令,主要获取到模块的短地址
			
			if (data.length < (data[4] & 0xFF))
				return 0;
			System.arraycopy(data, i + 2, sAddr, 0, 2);
			System.arraycopy(data, i + 4, pAddr, 0, 2);
			System.arraycopy(data, i + 6, lAddr, 0, 8);
			//nSub[0] = (byte)0; //子设备号

			//收到上报指令后，先回复模块一个上报指令，用于交互完成
			byte cmdRequestSubdevice[] = new byte[1];
			cmdRequestSubdevice[0] = (byte) COMMAND_DEVICE_REPORT;
			CommandToDevice(sAddr, 0x01, cmdRequestSubdevice);

			int subNum = data[i+1];
			// 请求设备信息，用于获取到设备的名称
			 if(subNum == 2){
                 RequestDeviceInfo(sAddr, (byte) 0);
                 try
                 {
                     Thread.currentThread();
                     Thread.sleep(100);//毫秒 
                 }
                 catch(Exception e){
                     
                 }
                 RequestDeviceInfo(sAddr, (byte) 1);
            }else 
            {
                 RequestDeviceInfo(sAddr, (byte) 0);
            }

		} else if ((data[i] & 0xFF) == COMMAND_SUBDEVICE_INFO)// 控制器请求的设备信息
		{
			int pos = 4;
			if (data.length < (data[4] & 0xFF))
				return 0;
			byte[] temp = new byte[14];
			int sensorNameLen = 0;
			
			System.arraycopy(data, i + pos, temp, 0, 14);
			java.util.Arrays.fill(RcvBuf, (byte) 0);
			for (int j = 0; j < temp.length; j++)
				if (temp[j] != 0) {
					sensorNameLen++;
				}
			byte[] sensorName = new byte[sensorNameLen];	
			//得到设备名称
			System.arraycopy(temp, 0, sensorName, 0, sensorNameLen);
			String sensorNameString = new String(sensorName);
		
			Message message = new Message();
			message.what = SENSORDEVMSG;
		
			//取得传感器的短地址
			System.arraycopy(data, 2, sAddr, 0, 2);
				
			Bundle bundle = new Bundle();
			bundle.putString("sensorName", sensorNameString);
			bundle.putByteArray("sensorAddr", sAddr);
			message.setData(bundle);
			myhandler.sendMessage(message);
				
		} else if (((data[1] & 0xFF) == COMMAND_DATABRIDGE)) { //获得设备数据
			int dataLen = 0;
			
			dataLen = data[4];
		
			if (data.length - 4 < dataLen) {
				return 0;
			}

			if (dataLen - 3 < 0) {
				return 0;
			}
			byte[] sensorData = new byte[dataLen - 3];
			Arrays.fill(sensorData, (byte) 0);
				
			//取得传感器的短地址
			System.arraycopy(data, 2, sAddr, 0, 2);
			System.arraycopy(data, i + 2, sensorData, 0, dataLen - 3);
			
			SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
            Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
            String TimeString = formatter.format(curDate);
             
			Message message = new Message();
			message.what = 2;
			
			Bundle bundle = new Bundle();
			bundle.putByteArray("sensorData", sensorData);
			bundle.putByteArray("sensorAddr", sAddr);
			bundle.putString("sensorTime", TimeString);
			bundle.putInt("SubNum", data[i+1]);
			
			message.setData(bundle);
			myhandler.sendMessage(message);
		}
		return 1;
	}
	
	//获取模块详细信息，包括短地址，设备名
	private void RequestDeviceInfo(byte[] sAddr, byte nSub) {
		byte cmdRequestSubdevice[] = new byte[2];

		int datalen = 0x02;

		cmdRequestSubdevice[0] = (byte) COMMAND_SUBDEVICE_INFO;
		cmdRequestSubdevice[1] = nSub;
		CommandToDevice(sAddr, datalen, cmdRequestSubdevice);
	}

	//读取模块的数据
	public void RequestDeviceData(byte[] sAddr, byte nSub) {
		int datalen = 0x02;

		byte cmdRequestSubdevice[] = new byte[2];
		cmdRequestSubdevice[0] = (byte) ZD_READ;
		cmdRequestSubdevice[1] = nSub;
		CommandToDevice(sAddr, datalen, cmdRequestSubdevice);
	}
	
	public void controlAct(byte[] sAddr, int subDev, int value) {
		byte cmdRequestSubdevice[] = new byte[3];
		cmdRequestSubdevice[0] = (byte) ZD_ACT;
		cmdRequestSubdevice[1] = (byte) subDev;
		cmdRequestSubdevice[2] = (byte) value;

		byte cmdDown[] = new byte[2];
		cmdDown[0] = (byte) FRAME_START_DOWN;
		cmdDown[1] = (byte) COMMAND_DATABRIDGE;
		byte datalen[] = new byte[1];
		datalen[0] = (byte) 0x03;

		try {
			mOutputStream.write(cmdDown);
			mOutputStream.write(sAddr);
			mOutputStream.write(datalen);
			mOutputStream.write(cmdRequestSubdevice);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void CommandToDevice(byte[] shortAddr, int len, byte[] data) {
		byte cmdDown[] = new byte[2];
		cmdDown[0] = (byte) FRAME_START_DOWN;
		cmdDown[1] = (byte) COMMAND_DATABRIDGE;
		byte datalen[] = new byte[1];
		datalen[0] = (byte) len;

		try {
			mOutputStream.write(cmdDown);
			mOutputStream.write(shortAddr);
			mOutputStream.write(datalen);
			mOutputStream.write(data);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	// 从字节数组到十六进制字符串转换
	public final static byte[] hex = "0123456789ABCDEF".getBytes();

	public static String Bytes2HexString(byte[] b) {

		byte[] buff = new byte[2 * b.length];

		for (int i = 0; i < b.length; i++) {

			buff[2 * i] = hex[(b[b.length - i - 1] >> 4) & 0x0f];
			buff[2 * i + 1] = hex[b[b.length - i - 1] & 0x0f];
		}
		return new String(buff);
	}
}
